/* 正版解释 */
class MyPromise {
    constructor(executor) {
        this.status = "pending"
        this.data = null
        this.resolvedCallbacks = []
        this.rejectedCallbacks = []
        try {
            executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (err) {
            this.reject(err)
        }
    }
    resolve(value) {
        if (this.status === "pending") {
            this.data = value
            this.status = "resolved"
            for (const func of this.resolvedCallbacks) {
                func(this.data)
            }
        }
    }
    reject(reason) {
        if (this.status === "pending") {
            this.data = reason
            this.status = "rejected"
            for (const func of this.rejectedCallbacks) {
                func(this.data)
            }
        }
    }
    then(onResolved, onRejected) {
        onResolved = typeof onResolved === "function" ? onResolved : (v) => v
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw(e)}
        let promise2 = new MyPromise((resolve, reject)=>{
            // 此处的this.status 和 this.data 指的是promise的
            // 箭头函数的作用 ()=> promise1  function undefined
            if (this.status === "pending") {
                this.onResolvedCallbacks.push((value) => {
                    setTimeout(() => {
                        try {
                            const x = onResolved(value)
                            this.resolvePromise(promise2, x, resolve, reject)
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                })
                this.onRejectedCallbacks.push((reason) => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(reason)
                            this.resolvePromise(promise2, x, resolve, reject)
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                })

            }
            if (this.status === "resolved") {
                setTimeout(() => {
                    try {
                        const x = onResolved(this.data)
                        this.resolvePromise(promise2, x, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }
                }, 0)
            }
            if (this.status === "rejectde") {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.data)
                        this.resolvePromise(x, promise2, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }
                }, 0)
            }
        })
        return promise2

    }
    // 根据x的类型改变promise2的状态，resolve和reject是改变promise2状态的
    resolvePromise(promise2, x, resolve, reject) {
        let call = false
        if (x === promise2) {
            return reject(new TypeError("Chaining"))
        } else if (x instanceof MyPromise) {
            if (x.status === "pending") {
                // 箭头函数 --- this --- 没有创建实例，this指向上一层作用域的this
                x.then((y) => {
                    this.resolvePromise(promise2, y, resolve, reject)
                }, reject)
            } else {
                x.then(resolve, reject)
            }
        } else if (Object.prototype.toString.call(x) === "[object Object]" || typeof x === "function") {
            try {
                const then = x.then
                if (typeof then === "function") {
                    x.then.call(x, (y) => {
                        if (call) return
                        call = true
                        this.resolvePromise(promise2, y, resolve, reject)
                    }, r => {
                        if (call) return
                        call = true
                        reject(r)
                    })
                } else {
                    if (call) return
                    call = true
                    resolve(x)
                }
            } catch (err) {
                if (call) return
                call = true
                reject(err)
            }
        } else {
            resolve(x)
        }

    }
    catch(onRejected){
        return this.then(null,onRejected)
    }
    done(){
        this.catch(reason =>{
            throw reason
        })
    }
    finally(fn){
        return this.then(value =>{
            fn()
            return value
        }, reason => {
            fn()
            throw reason
        })
    }
    static all(promiseList){
        let res = []
        let i=1;
        let count = promiseList.length
        return new MyPromise((resolve, reject)=>{
            for(const p in promiseList){
                p.then(value=>{
                    res.push(value)
                    if(i===count) resolve(res)
                }, reject)
                i++
            }
        })
    }
    static race(promiseList){
        return new MyPromise((resolve, reject)=>{
            for(const p in promiseList){
                p.then(value => {
                    resolve(value)
                },reject)
            }
        })
    }
    static resolve(value){
        let promise1 = new MyPromise((resolve, reject)=>{
            this.resolvePromise(promise1,value, resolve, reject)
        })
        return promise1
    }
    static reject(reason){
        return new Mypromise((resolve, reject)=>{
            reject(reason)
        })
    }
}